{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 装饰器"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.1 函数核心回顾\n",
    "\n",
    "- 函数也是对象。我们可以把函数赋予变量\n",
    "- 把函数当作参数，传入另一个函数中，\n",
    "- 函数里定义函数，也就是函数的嵌套、\n",
    "- 函数的返回值也可以是函数对象（闭包）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Got a message: hello world\n"
     ]
    }
   ],
   "source": [
    "def func(message):\n",
    "    def get_message(message):\n",
    "        print('Got a message: {}'.format(message))\n",
    "    return get_message(message)\n",
    "\n",
    "func('hello world')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Got a message: hello world1,param:hello world\n"
     ]
    }
   ],
   "source": [
    "def func_closure(mess):\n",
    "    def get_message(message):\n",
    "        print('Got a message: {},param:{}'.format(mess,message))\n",
    "    return get_message\n",
    "\n",
    "send_message = func_closure(\"hello world1\")\n",
    "send_message('hello world')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2 简单的装饰器\n",
    "\n",
    "- 简单装饰器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "wrapper of decorator\n",
      "hello world\n",
      "-----------------\n",
      "wrapper of decorator\n",
      "wrapper of decorator\n",
      "hello world\n"
     ]
    }
   ],
   "source": [
    "def my_decorator(func):\n",
    "    def wrapper():\n",
    "        print('wrapper of decorator')\n",
    "        func()\n",
    "    return wrapper\n",
    "\n",
    "def greet():\n",
    "    print('hello world')\n",
    "\n",
    "greet = my_decorator(greet)\n",
    "greet()\n",
    "print('-----------------')\n",
    "ab = my_decorator(greet)\n",
    "ab()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里的@，我们称之为语法糖，@my_decorator就相当于前面的greet=my_decorator(greet)语句，只不过更加简洁。因此，如果你的程序中有其它函数需要做类似的装饰，你只需在它们的上方加上@decorator就可以了，这样就大大提高了函数的重复利用和程序的可读性。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "wrapper of decorator\n",
      "hello world\n"
     ]
    }
   ],
   "source": [
    "def my_decorator(func):\n",
    "    def wrapper():\n",
    "        print('wrapper of decorator')\n",
    "        func()\n",
    "    return wrapper\n",
    "\n",
    "@my_decorator\n",
    "def greet():\n",
    "    print('hello world')\n",
    "\n",
    "greet()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.3 带有参数的装饰器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "wrapper of:<class 'function'> decorator:<class 'str'>\n",
      "hello world\n"
     ]
    }
   ],
   "source": [
    "def my_decorator(func):\n",
    "    def wrapper(message):\n",
    "        print('wrapper of:{} decorator:{}'.format(type(func),type(message)))\n",
    "        func(message)\n",
    "    return wrapper\n",
    "\n",
    "@my_decorator\n",
    "def greet(message):\n",
    "    print(message)\n",
    "\n",
    "greet('hello world')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "wrapper of decorator\n",
      "args:('hello world', '1', '2'),kwargs:{'name': 'python', 'age': '20', 'sex': 'male'}\n",
      "('hello world', '1', '2') {'name': 'python', 'age': '20', 'sex': 'male'}\n"
     ]
    }
   ],
   "source": [
    "### 多参数和类型检查\n",
    "def my_decorator(func):\n",
    "    def wrapper(*args,**kwargs):\n",
    "        print('wrapper of decorator')\n",
    "        print('args:{},kwargs:{}'.format(args,kwargs))\n",
    "        func(*args,**kwargs)\n",
    "    return wrapper\n",
    "\n",
    "@my_decorator\n",
    "def greet(*message,**name):\n",
    "    print(message,name)\n",
    "\n",
    "greet('hello world','1','2',name='python',age='20',sex='male')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.4 带有自定义参数的装饰器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "wrapper of decorator\n",
      "hello world\n",
      "wrapper of decorator\n",
      "hello world\n",
      "wrapper of decorator\n",
      "hello world\n",
      "wrapper of decorator\n",
      "hello world\n",
      "Help on function greet in module __main__:\n",
      "\n",
      "greet(message)\n",
      "\n"
     ]
    }
   ],
   "source": [
    "import functools\n",
    "def repeat(num):\n",
    "    def my_decorator(func):\n",
    "        @functools.wraps(func)\n",
    "        def wrapper(*args, **kwargs):\n",
    "            for i in range(num):\n",
    "                print('wrapper of decorator')\n",
    "                func(*args, **kwargs)\n",
    "        return wrapper\n",
    "    return my_decorator\n",
    "\n",
    "\n",
    "@repeat(4)\n",
    "def greet(message):\n",
    "    print(message)\n",
    "\n",
    "greet('hello world')\n",
    "\n",
    "greet.__name__\n",
    "help(greet)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.5 类装饰器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "num of calls is:1\n",
      "hello world\n",
      "num of calls is:2\n",
      "hello world\n"
     ]
    }
   ],
   "source": [
    "class Count:\n",
    "    def __init__(self,func):\n",
    "        self.func = func\n",
    "        self.num_calls = 0\n",
    "\n",
    "    def __call__(self, *args, **kwargs):\n",
    "        self.num_calls += 1\n",
    "        print('num of calls is:{}'.format(self.num_calls))\n",
    "        return self.func(*args,**kwargs)\n",
    "\n",
    "@Count\n",
    "def greet(message):\n",
    "    print(message)\n",
    "\n",
    "greet('hello world')\n",
    "greet('hello world')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.6 装饰器嵌套\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "execute decorator2\n",
      "execute decorator1\n",
      "hello world\n"
     ]
    }
   ],
   "source": [
    "import functools\n",
    "\n",
    "def my_decorator1(func):\n",
    "    @functools.wraps(func)\n",
    "    def wrapper(*args, **kwargs):\n",
    "        print('execute decorator1')\n",
    "        func(*args, **kwargs)\n",
    "    return wrapper\n",
    "\n",
    "\n",
    "def my_decorator2(func):\n",
    "    @functools.wraps(func)\n",
    "    def wrapper(*args, **kwargs):\n",
    "        print('execute decorator2')\n",
    "        func(*args, **kwargs)\n",
    "    return wrapper\n",
    "\n",
    "@my_decorator2\n",
    "@my_decorator1\n",
    "def greet(message):\n",
    "    print(message)\n",
    "\n",
    "\n",
    "greet('hello world')\n",
    "\n",
    "# decorator1(decorator2(func))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.7 装饰器应用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### 3.7.1 身份认证\n",
    "\n",
    "```python\n",
    "import functools\n",
    "\n",
    "def authenticate(func):\n",
    "    @functools.wraps(func)\n",
    "    def wrapper(*args, **kwargs):\n",
    "        request = args[0]\n",
    "        if check_user_logged_in(request): # 如果用户处于登录状态\n",
    "            return func(*args, **kwargs) # 执行函数post_comment() \n",
    "        else:\n",
    "            raise Exception('Authentication failed')\n",
    "    return wrapper\n",
    "    \n",
    "@authenticate\n",
    "def post_comment(request, ...)\n",
    "    ...\n",
    " \n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### 3.7.2 日志记录\n",
    "\n",
    "```python\n",
    "import time\n",
    "import functools\n",
    "\n",
    "def log_execution_time(func):\n",
    "    @functools.wraps(func)\n",
    "    def wrapper(*args, **kwargs):\n",
    "        start = time.perf_counter()\n",
    "        res = func(*args, **kwargs)\n",
    "        end = time.perf_counter()\n",
    "        print('{} took {} ms'.format(func.__name__, (end - start) * 1000))\n",
    "        return res\n",
    "    return wrapper\n",
    "    \n",
    "@log_execution_time\n",
    "def calculate_similarity(items):\n",
    "    ...\n",
    "\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### 3.7.3 输入合理性检查\n",
    "\n",
    "```python\n",
    "\n",
    "import functools\n",
    "\n",
    "def validation_check(input):\n",
    "    @functools.wraps(func)\n",
    "    def wrapper(*args, **kwargs): \n",
    "        ... # 检查输入是否合法\n",
    "    \n",
    "@validation_check\n",
    "def neural_network_training(param1, param2, ...):\n",
    "    ...\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### 3.7.4 缓存\n",
    "\n",
    "```python\n",
    "@lru_cache\n",
    "def check(param1, param2, ...) # 检查用户设备类型，版本号等等\n",
    "    ...\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. 总结\n",
    "\n",
    "- 所谓的装饰器，其实就是通过装饰器函数，来修改原函数的一些功能，使得原函数不需要修改。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
